package com.app.commond.sys;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.app.conf.AppConfig;
import com.app.exception.CmdAlreadyExists;
import com.app.exception.LoadCmdException;
import com.app.protocol.CmdKeyUtil;

import soft.common.ClassUtil;
import soft.common.InstanceUitl;
import soft.common.StaticClass;
import soft.net.exception.DataIsNullException;

/**
 * 命令管理中心
 * 
 * @author fanpei
 * @date 2018-09-16 22:29
 *
 */
public class CmdFactoryCenter extends StaticClass {

	private static Map<String, Class<CmdBase>> cmdStores = new HashMap<>();

	/**
	 * 加载所有命令
	 * 
	 * @throws LoadCmdException
	 */
	public static void loadAllCmd() throws LoadCmdException {
		String packageName = AppConfig.CMDPACKGENAME;
		Set<Class<?>> clazzs = ClassUtil.getClasses(packageName, AppCmd.class);
		if (clazzs != null) {
			for (Class<?> cls : clazzs) {
				try {
					if (cls.getSuperclass().equals(CmdBase.class)) {
						@SuppressWarnings("unchecked")
						Class<CmdBase> cmd = (Class<CmdBase>) cls;
						InstanceUitl.createObject(cmd);// 初始化时新建对象，加快程序后续新建对象的性能消耗和速度
						AppCmd anono = cls.getAnnotation(AppCmd.class);
						String cmdKey = CmdKeyUtil.getCmdKey(anono.devAddr(), anono.funcCode());
						registerCmd(cmdKey, cmd);
					}
				} catch (Exception e) {
					throw new LoadCmdException("load cmd err:" + cls.getName()
							+ "please check if this class  contain default constructor?");
				}
			}
		}

	}

	/**
	 * 注册命令
	 * 
	 * @param cmdkey
	 * @param cmd
	 * @throws CmdAlreadyExists
	 */
	public static void registerCmd(String cmdkey, Class<CmdBase> cmdClass) throws CmdAlreadyExists {
		if (cmdStores.containsKey(cmdkey))
			throw new CmdAlreadyExists(cmdkey);

		cmdStores.put(cmdkey, cmdClass);
	}

	/**
	 * 获取cmd
	 * 
	 * @param protocol 协议
	 * @return
	 * @throws DataIsNullException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws Exception
	 */
	public static CmdBase getCmd(String cmdkey)
			throws InstantiationException, IllegalAccessException, DataIsNullException {
		Class<CmdBase> clazz = cmdStores.get(cmdkey);
		return InstanceUitl.createObject(cmdkey, clazz);
	}

	public static void main(String[] args) {
		try {
			AppConfig.readConf();
			loadAllCmd();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
